class SmartDiffDataLoader extends DynamicDataLoader {
  /**
   * @param {string} containerSelector - DOM容器的选择器
   * @param {Array} initialData - 初始数据数组
   * @param {Function} renderCallback - 渲染每个数据项的回调函数
   * @param {Object} animationOptions - 动画选项
   *   @param {string} animationOptions.enterAnimation - 新增项的进入动画
   *   @param {string} animationOptions.exitAnimation - 删除项的退出动画
   *   @param {string} animationOptions.updateAnimation - 更新项的动画
   *   @param {number} animationOptions.animationDuration - 动画持续时间
   */
  constructor(
    containerSelector,
    initialData = [],
    renderCallback,
    animationOptions = {}
  ) {
    super(containerSelector, initialData, renderCallback);

    this.animationOptions = {
      enterAnimation: 'fade-in',
      exitAnimation: 'fade-out',
      updateAnimation: 'pulse-update',
      animationDuration: 300,
      ...animationOptions,
    };

    this.previousData = [...initialData];
    this.container.style.position = 'relative';
  }

  /**
   * 计算数据差异
   * @param {Array} oldData - 旧数据
   * @param {Array} newData - 新数据
   * @returns {Object} 差异结果
   */
  calculateDiff(oldData, newData) {
    const diff = {
      added: [],
      removed: [],
      updated: [],
      unchanged: [],
    };

    // 创建旧数据的映射
    const oldMap = new Map();
    oldData.forEach((item, index) => {
      oldMap.set(this.getItemKey(item), { item, index });
    });

    // 检查新数据
    newData.forEach((newItem, newIndex) => {
      const key = this.getItemKey(newItem);
      if (!oldMap.has(key)) {
        diff.added.push({ item: newItem, index: newIndex });
      } else {
        const oldEntry = oldMap.get(key);
        if (!this.isItemEqual(oldEntry.item, newItem)) {
          diff.updated.push({
            oldItem: oldEntry.item,
            newItem,
            oldIndex: oldEntry.index,
            newIndex,
          });
        } else {
          diff.unchanged.push({
            item: newItem,
            oldIndex: oldEntry.index,
            newIndex,
          });
        }
        oldMap.delete(key);
      }
    });

    // 剩下的就是被删除的
    oldMap.forEach((value) => {
      diff.removed.push(value);
    });

    return diff;
  }

  /**
   * 获取数据项的唯一键
   * @param {*} item - 数据项
   * @returns {string|number} 唯一键
   */
  getItemKey(item) {
    // 默认使用JSON字符串化作为键，可以根据实际数据结构覆盖此方法
    return JSON.stringify(item);
  }

  /**
   * 比较两个数据项是否相等
   * @param {*} a - 第一个数据项
   * @param {*} b - 第二个数据项
   * @returns {boolean} 是否相等
   */
  isItemEqual(a, b) {
    // 默认使用严格相等，可以根据需要覆盖
    return this.getItemKey(a) === this.getItemKey(b);
  }

  /**
   * 智能渲染（只对变更项应用动画）
   */
  async render() {
    const diff = this.calculateDiff(this.previousData, this.data);
    this.previousData = [...this.data];

    // 1. 处理删除的项目
    await this.handleRemovedItems(diff.removed);

    // 2. 处理保留的项目（可能需要移动位置）
    this.handleUnchangedItems(diff.unchanged);

    // 3. 处理新增和更新的项目
    await this.handleAddedAndUpdatedItems(diff.added, diff.updated);
  }

  /**
   * 处理被删除的项目
   */
  async handleRemovedItems(removedItems) {
    if (removedItems.length === 0) return;

    const children = Array.from(this.container.children);
    const promises = removedItems.map(({ index }) => {
      const element = children[index];
      if (!element) return Promise.resolve();

      return new Promise((resolve) => {
        element.classList.add(this.animationOptions.exitAnimation);

        setTimeout(() => {
          if (element.parentNode) {
            element.remove();
          }
          resolve();
        }, this.animationOptions.animationDuration);
      });
    });

    await Promise.all(promises);
  }

  /**
   * 处理未变更的项目（只更新位置）
   */
  handleUnchangedItems(unchangedItems) {
    unchangedItems.forEach(({ oldIndex, newIndex }) => {
      const children = Array.from(this.container.children);
      const element = children[oldIndex];
      if (element && oldIndex !== newIndex) {
        // 如果位置变了但内容没变，直接移动DOM位置
        if (newIndex >= this.container.children.length) {
          this.container.appendChild(element);
        } else {
          this.container.insertBefore(
            element,
            this.container.children[newIndex]
          );
        }
      }
    });
  }

  /**
   * 处理新增和更新的项目
   */
  async handleAddedAndUpdatedItems(addedItems, updatedItems) {
    const allChanges = [...addedItems, ...updatedItems];
    if (allChanges.length === 0) return;

    const promises = allChanges.map(({ newItem, newIndex }) => {
      return new Promise((resolve) => {
        const element = this.renderCallback(newItem, newIndex);
        if (!element) return resolve();

        // 设置初始状态
        element.style.opacity = '0';
        element.classList.add(this.animationOptions.enterAnimation);

        // 插入到正确位置
        if (newIndex >= this.container.children.length) {
          this.container.appendChild(element);
        } else {
          this.container.insertBefore(
            element,
            this.container.children[newIndex]
          );
        }

        // 触发动画
        requestAnimationFrame(() => {
          element.style.opacity = '1';

          setTimeout(() => {
            element.classList.remove(this.animationOptions.enterAnimation);
            element.style.opacity = '';
            resolve();
          }, this.animationOptions.animationDuration);
        });
      });
    });

    await Promise.all(promises);
  }

  /**
   * 更新数据（覆盖父类方法）
   */
  async updateData(newData) {
    this.data = [...newData];
    await this.render();
    this.trigger('dataUpdated', this.data);
  }

  /**
   * 添加项目（覆盖父类方法）
   */
  async addItem(item) {
    this.data.push(item);
    await this.render();
    this.trigger('itemAdded', item);
  }

  /**
   * 删除项目（覆盖父类方法）
   */
  async removeItems(predicate) {
    const removedItems = this.data.filter(predicate);
    this.data = this.data.filter((item) => !predicate(item));
    await this.render();
    this.trigger('itemsRemoved', removedItems);
  }
}
